//
// Created by cube on 2020/10/26.
//

#include <gtest/gtest.h>

#include "../Base/Object.h"
#include "../Base/AOP_IOC.h"

#include <functional>

using namespace Lib;

class MyObject : public Object{
public:
    LIB_OBJECT
    LIB_SIGNAL_OBJ(signal_a,int)
    LIB_SIGNAL_OBJ(signal_b,int)
public:
    MyObject(Object* parent = nullptr) : Object(parent){

    }
    virtual ~MyObject(){std::cout<<"delete "<<std::endl;}
    void emit_ff(int a){
        emit(signal_a,a);
    }

protected:
    bool filter(EventAgent& event) override {
        std::cout<<this<<"  filter "<<event->getType()<<std::endl;
        return Object::filter(event);
    }
    void event(EventAgent& event) override {
        std::cout<<this<<"  event "<<event->getType()<<std::endl;
        Object::event(event);
    }

};


TEST(Base_TEST,Object){
    auto obj = new MyObject();
    obj->setLoop(new EventLoop());
    auto obj1 = new MyObject(obj);
    obj->loop_start.connect([](){std::cout<<"loop start"<<std::endl;});
    obj->loop_stop.connect([](){std::cout<<"loop stop"<<std::endl;});
    obj->signal_a.connect([](int a){std::cout<<"signal a "<<a<<std::endl;});
    obj->signal_b.connect([&](int a){
        std::cout<<"signal b "<<a<<std::endl;
        obj->loop()->exit();
    });
    obj->signal_a.connect(obj->signal_b);
    obj->setLoop(new EventLoop());
    obj->emit_ff(3);
    obj->loop()->exec();
    delete obj;
}


class Obj{
public:
    void fff(){
        std::cout<<"llll"<<std::endl;
    }
};

//int fff(){return 3;}
//int fff1(){return 44;}
//void fun(int a){int i = 0; i++;}
//void obj_f(Obj* obj){std::cout<<"start"<<std::endl;}
//void obj_e(Obj* obj){std::cout<<"end"<<std::endl;}
//
//
//void ffffe(int a){std::cout<<"sss"<<a<<std::endl;}
//
//class Ob {
//public:
//    AUTOWARDITEM(ppp,void,int)
//
//    static void start(Ob& obj){
//        std::cout<<"--start"<<std::endl;
//    }
//
//    static void end(Ob& obj){
//        std::cout<<"--end"<<std::endl;
//    }
//
//    void ff(int a){
//        ppp()(a);
//    }
//};
//void FF(Ob& obj){std::cout<<"---1111"<<std::endl;}
//void FE(Ob& ob){std::cout<<"---fe"<<std::endl;}


void fa(){std::cout<<"fa"<<std::endl;}
void fff(int,int,int){}
int ffff(){
    std::cout<<"zzzzz"<<std::endl;
    return 3;
}

TEST(Base_TEST,IOC_T1){
    IOC::autoward<void>();
    IOC::registerAutoward<void>(fa);
    IOC::autoward<void>();
}

TEST(Base_TEST,AOP_IOC_IOC_Test){
//    auto f = IOC::make_FunctionPtr(fff);
//    auto f0 = IOC::make_FunctionPtr(fff,4);
//    auto f1 = IOC::AutowardItem<void,int,int,int>();
//    f1.set(fff);
//    auto f2 = std::function(fff);
//    auto f3 = std::bind(fff,4,5,6);
//
//    int max = 1000000000;
//    std::time_t time;
//    time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
//    for(int i=0;i<max;i++)f(2,3,4);
//    std::cout<<std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) - time<<std::endl;
//    std::cout<<"---------"<<std::endl;
//    time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
//    for(int i=0;i<max;i++)f0(2,3);
//    std::cout<<std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) - time<<std::endl;
//
//    std::cout<<"---------"<<std::endl;
//    time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
//    for(int i=0;i<max;i++)fff(1,2,3);
//    std::cout<<std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) - time<<std::endl;
//    std::cout<<"---------"<<std::endl;
//    time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
//    for(int i=0;i<max;i++)f1(1,2,3);
//    std::cout<<std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) - time<<std::endl;
//
//    std::cout<<"---------"<<std::endl;
//    time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
//    for(int i=0;i<max;i++)f2(1,2,3);
//    std::cout<<std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) - time<<std::endl;
//    std::cout<<"---------"<<std::endl;
//    time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
//    for(int i=0;i<max;i++)f3();
//    std::cout<<std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) - time<<std::endl;

}

struct AopTObj1{void ff(){std::cout<<"ff"<<std::endl;}};
void aop_f1(AopTObj1& obj){std::cout<<"start"<<std::endl;}
void aop_f2(AopTObj1& obj){std::cout<<"end"<<std::endl;}
void aop_f3(AopTObj1& obj){std::cout<<"start"<<std::endl;}
void aop_f4(AopTObj1& obj){std::cout<<"end"<<std::endl;}

TEST(Base_TEST,AOP_T1){
    AopTObj1 obj;
    auto asp1 = AOP::AspectItem(obj,aop_f1,aop_f2);
    asp1()->ff();
    (*asp1()).ff();

    auto asp2 = AOP::Aspect_Superposition(obj,aop_f1,aop_f2);
    asp2.add(aop_f3,aop_f4);
    asp2()->ff();
    (*asp2()).ff();

}